Weitere ähnliche Inhalte Ähnlich wie Celery eine asynchrone task queue (nicht nur) für django Ähnlich wie Celery eine asynchrone task queue (nicht nur) für django (20) Mehr von Markus Zapke-Gründemann Mehr von Markus Zapke-Gründemann (11) Celery eine asynchrone task queue (nicht nur) für django1. Celery
Eine asynchrone Task Queue
(nicht nur) für Django
Markus Zapke-Gründemann
www.keimlink.de
Leipzig Python User Group 12.10.2010
3. Warum eine
Task Queue?
• Entkoppeln von Informationsproduzenten
und -konsumenten
• Asynchrone Verarbeitung
• Skalierbarkeit
5. Produzent Konsument
Task
Produzent Konsument
Queue
Produzent Konsument
6. Produzent Konsument
Task
Produzent Konsument
Queue
Produzent Konsument
7. Produzent Konsument
Task
Produzent Konsument
Queue
Produzent Konsument
8. Celery
• Autor: Ask Solem Hoel
• RabbitMQ, Stomp, Redis und Ghetto Queue
• Clustering mit RabbitMQ
• Parallele Ausführung
• Zeitgesteuerte Ausführung
9. Celery
• Rückgabewert sofort oder später
verarbeiten
• Speichern der Rückgabe in „Result Stores“
• Webhooks
• Serialisierung (Pickle, JSON,YAML)
• Wiederholen abgebrochener Tasks
13. Python Task
# Task als Klasse
from celery.task import Task
from myproject.models import User
class CreateUserTask(Task):
def run(self, username, password):
User.create(username, password)
>>> from tasks import CreateUserTask
>>> CreateUserTask().delay('john', 'secret')
# Task als Funktion mit Decorator
from celery.decorators import task
from myproject.models import User
@task
def create_user(username, password):
User.create(username, password)
>>> from tasks import create_user
>>> create_user.delay('john', 'secret')
14. Python Task
@task() # Benutzt pickle, um das Objekt zu serialisieren.
def check_means(user):
return user.has_means()
>>> from tasks import check_means
>>> result = check_means.delay(user)
>>> result.ready() # Gibt True zurück wenn der Task beendet ist.
False
>>> result.result # Task ist noch nicht beendet, kein Ergebnis verfügbar.
None
>>> result.get() # Warten bis der Task fertig ist und Ergebnis zurückgeben.
93.27
>>> result.result # Jetzt ist ein Ergebnis da.
93.27
>>> result.successful() # War der Task erfolgreich?
True
15. Python Task
Konfiguration
# celeryconfig.py
BROKER_HOST = "localhost"
BROKER_PORT = 5672
BROKER_USER = "myuser"
BROKER_PASSWORD = "mypassword"
BROKER_VHOST = "myvhost"
CELERY_RESULT_BACKEND = "database"
CELERY_RESULT_DBURI = "mysql://user:password@host/dbname"
CELERY_IMPORTS = ("tasks", )
$ celeryd --loglevel=INFO
16. Zeitgesteuerter Task
# Periodic task
from celery.decorators import periodic_task
from datetime import timedelta
@periodic_task(run_every=timedelta(seconds=30))
def every_30_seconds():
print("Running periodic task!")
# crontab
from celery.task.schedules import crontab
from celery.decorators import periodic_task
@periodic_task(run_every=crontab(hour=7, minute=30, day_of_week=1))
def every_monday_morning():
print("Execute every Monday at 7:30AM.")
$ celerybeat
$ celeryd -B
18. Django Task
Installation
$ pip install django-celery
$ easy_install django-celery
20. Django Task
Spamfilter
Produzent
blog.views.add_comment
21. Django Task
Spamfilter
Produzent
blog.views.add_comment
Comment
Model
22. Django Task
Spamfilter
Produzent
blog.views.add_comment
comment.save()
Comment
Model
23. Django Task
Spamfilter
Task
Produzent Queue
blog.views.add_comment
comment.save()
Comment
Model
24. Django Task
Spamfilter
Task
Produzent Konsument
Queue
blog.views.add_comment blog.tasks.spam_filter
comment.save()
Comment
Model
25. Django Task
Spamfilter
blog.tasks.spam_filter.delay(comment.id,
remote_addr)
Task
Produzent Konsument
Queue
blog.views.add_comment blog.tasks.spam_filter
comment.save()
Comment
Model
26. Django Task
Spamfilter
blog.tasks.spam_filter.delay(comment.id,
remote_addr)
Task
Produzent Konsument
Queue
blog.views.add_comment blog.tasks.spam_filter
comment.save()
Comment
Model
27. Django Task
Spamfilter
blog.tasks.spam_filter.delay(comment.id,
remote_addr)
Task
Produzent Konsument
Queue
blog.views.add_comment blog.tasks.spam_filter
comment.is_spam = True
comment.save()
comment.save()
Comment
Model
28. blog/tasks.py
@task
def spam_filter(comment_id, remote_addr=None, **kwargs):
logger = spam_filter.get_logger(**kwargs)
logger.info("Running spam filter for comment %s" % comment_id)
comment = Comment.objects.get(pk=comment_id)
current_domain = Site.objects.get_current().domain
akismet = Akismet(settings.AKISMET_KEY, "http://%s" % domain)
if not akismet.verify_key():
raise ImproperlyConfigured("Invalid AKISMET_KEY")
is_spam = akismet.comment_check(user_ip=remote_addr,
comment_content=comment.comment,
comment_author=comment.name,
comment_author_email=comment.email_address)
if is_spam:
comment.is_spam = True
comment.save()
return is_spam
29. Django Task
Konfiguration
# settings.py
INSTALLED_APPS += ("djcelery", )
import djcelery
djcelery.setup_loader()
BROKER_HOST = "localhost"
BROKER_PORT = 5672
BROKER_USER = "myuser"
BROKER_PASSWORD = "mypassword"
BROKER_VHOST = "myvhost"
$ python manage.py syncdb
$ python manage.py celeryd -l info
31. Webhook
# POST
>>> from celery.task.http import URL
>>> res = URL("http://example.com/multiply").get_async(x=10, y=10)
>>> res.get() # {"status": "success", "retval": 100}
100
# GET
>>> from celery.task.http import HttpDispatchTask
>>> url = "http://example.com/multiply"
>>> res = HttpDispatchTask.delay(url, method="GET", x=10, y=10)
>>> res.get() # {"status": "success", "retval": 100}
100
33. Lizenz
Dieses Werk ist unter einem Creative Commons
Namensnennung-Weitergabe unter gleichen
Bedingungen 3.0 Unported Lizenzvertrag
lizenziert.
Um die Lizenz anzusehen, gehen Sie bitte zu
http://creativecommons.org/licenses/by-sa/3.0/
oder schicken Sie einen Brief an Creative
Commons, 171 Second Street, Suite 300, San
Francisco, California 94105, USA.